package com.jchy.renderit.core;

import com.jchy.renderit.displayable.*;

import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.reflect.Method;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class JPropertiesAndMethods extends JFrame
{
    private Object anObject;
    private JPanel pamPanel; 
    private JPanel noPamPanel;
    private JPanel topBottomPanel;
    private int c;
    private ArrayList<Method> paramMethodList;
    private ArrayList<Method> noParamMethodList;

	private static final long serialVersionUID = 999;

    public JPropertiesAndMethods()
    {
        this(new BilliardStripe());
    }

    public JPropertiesAndMethods(Object inObject)
    {
        super("Properties and Methods of a(n) " + inObject.getClass().getName() + " object.");

        anObject=inObject;
        
        addWindowListener(new WindowAdapter() 
        {
            public void windowClosing(WindowEvent e)
            {
                System.exit(0);
            }
        });

        paramMethodList = new ArrayList<Method>();
        noParamMethodList = new ArrayList<Method>();
        for(c=0; c<anObject.getClass().getMethods().length;c++)
        {
        	Method thisMethod=anObject.getClass().getMethods()[c];            
            Class methodReturnType=thisMethod.getReturnType();
            int nonPrimitiveParams = 0;
            for(int a=0; a<thisMethod.getParameterTypes().length;a++)
            {
            	if(!thisMethod.getParameterTypes()[a].isPrimitive())
            		nonPrimitiveParams++;
            }
            
        	if(!"java.lang.Object".equalsIgnoreCase(thisMethod.getDeclaringClass().getName())
        	   && "void".equalsIgnoreCase(methodReturnType.getName()) 
        	   && thisMethod.getParameterTypes().length > 0
        	   && nonPrimitiveParams == 0)
        		paramMethodList.add(thisMethod);
        	
        	if(!"java.lang.Object".equalsIgnoreCase(thisMethod.getDeclaringClass().getName())
             	   && !"void".equalsIgnoreCase(methodReturnType.getName()) 
             	   && thisMethod.getParameterTypes().length == 0
             	   && methodReturnType.isPrimitive())
             		noParamMethodList.add(thisMethod);
        	
        }

        pamPanel=new JPanel();
        pamPanel.setLayout(new GridLayout(paramMethodList.size(),2));  
        for(c=0; c<paramMethodList.size();c++)
        {
        	Method thisMethod=paramMethodList.get(c);            
            Class methodReturnType=thisMethod.getReturnType();

            MethButton mBtn=new MethButton();
            mBtn.setObject(anObject);
            mBtn.setMethod(thisMethod);
            pamPanel.add(mBtn);

            JPanel meth=new JPanel();
            meth.setLayout(new FlowLayout());

            meth.add(new JLabel( methodReturnType.getName() ));

            if(methodReturnType.isPrimitive()
               && !(methodReturnType.getName().equals("void") ) )
                meth.add(new JTextField("     "));

            meth.add(new JLabel( thisMethod.getName() ));

            meth.add(new JLabel( "(" ));

            for(int a=0; a<thisMethod.getParameterTypes().length;a++)
            {
                Class thisParam=thisMethod.getParameterTypes()[a];

                if(a>0) meth.add(new JLabel( "," ));
                meth.add(new JLabel( thisParam.getName() ));
                if(thisParam.isPrimitive())
                    meth.add(new JTextField("     "));
            }
            meth.add(new JLabel( ")" ));

            pamPanel.add(meth);
        }
        
        noPamPanel=new JPanel();
        noPamPanel.setLayout(new GridLayout(noParamMethodList.size(),1));  
        for(c=0; c<noParamMethodList.size();c++)
        {
        	Method thisMethod=noParamMethodList.get(c);            
            Class methodReturnType=thisMethod.getReturnType();

            JPanel meth=new JPanel();
            meth.setLayout(new FlowLayout());

            meth.add(new JLabel( methodReturnType.getName() ));

            if(methodReturnType.isPrimitive()
               && !(methodReturnType.getName().equals("void") ) )
                meth.add(new JTextField("     "));

            meth.add(new JLabel( thisMethod.getName() ));

            meth.add(new JLabel( "(" ));

            for(int a=0; a<thisMethod.getParameterTypes().length;a++)
            {
                Class thisParam=thisMethod.getParameterTypes()[a];

                if(a>0) meth.add(new JLabel( "," ));
                meth.add(new JLabel( thisParam.getName() ));
                if(thisParam.isPrimitive())
                    meth.add(new JTextField("     "));
            }
            meth.add(new JLabel( ")" ));

            noPamPanel.add(meth);
        }

        topBottomPanel = new JPanel();
        topBottomPanel.setLayout(new GridLayout(2,1));  
        topBottomPanel.add(noPamPanel);
        topBottomPanel.add(pamPanel);
        
        getContentPane().add(topBottomPanel);
        buildMenu();
        pack();
              
    }

    private void buildMenu()
    {
        // Instantiates JMenuBar, JMenu,
        // and JMenuItem.
        JMenuBar mb = new JMenuBar();
        JMenu menu = new JMenu("File");
        JMenuItem item = new JMenuItem("Exit");
        //Closes the application from the Exit 
        //menu item.
        item.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                System.exit(0);
            }
             
        });// Ends method

        //Adds the item to the menu object
        menu.add(item);
        //Adds the menu object with item
        //onto the menu bar
        mb.add(menu); 
        //Sets the menu bar in the frame
        setJMenuBar(mb);
    }

    public static void main(String[] args)
    { 
        JPropertiesAndMethods pam = new JPropertiesAndMethods();
        pam.setSize(765, 690);
        pam.setBackground(Color.white);
        pam.setVisible(true);
    }

}

class MethButton extends JButton
{
    private Method method;
	private static final long serialVersionUID = 999;
    private Object object;
	
    MethButton()
    {
        this("Run");
    }

    MethButton(String inString)
    {
        super(inString);
    }

    public void setToolTipText()
    {
        super.setToolTipText("Executes " + method.getName() );
    }

    public void setMethod(Method inMethod)
    {
        method=inMethod;
        setToolTipText();
        super.addActionListener(
            new ActionListener(){
                public void actionPerformed(ActionEvent e)
                {
                    System.out.println("Executed " + method.getName() );
                }
            }
        );
    }

    public void setObject(Object inObject)
    {
        object=inObject;
    }
    
    public Object getObject()
    {
    	return object;
    }
}